<?php
namespace Pinenut\Model2;

class Updater extends \Pinenut\Model2\Finder {
	

	const OP_ADDTOSET = 'addToSet';
	const OP_INC = 'inc';
	const OP_SET = 'set';
	const OP_REMOVEFROMSET = 'removeFromSet';
		
	public $operators = array(); // хранит операторы модификации
								// массив где ключ - операции, а значения пары - поле->значение
	
	public $upsert = false;
	
	public $insert = false;
	
	public $delete = false;
	
	/**
	 * Добавляем записи во множество
	 * 
	 * @param string $field имя поля множества 
	 * @param mixed $value запись множества
	 * @return \Pinenut\Model2\Updater
	 */
	function addToSet($field, $value) {
		$this->operators[static::OP_ADDTOSET][$field] = $value;
		return $this;
	}
	
	/**
	 * Удаляем запись из множества
	 *
	 * @param string $field имя поля множества
	 * @param mixed $value запись множества
	 * @return \Pinenut\Model2\Updater
	 */
	function removeFromSet($field, $value) {
		$this->operators[static::OP_REMOVEFROMSET][$field][] = $value;
		return $this;
	}
	
	
	/**
	 * @param string $field
	 * @param int $value
	 * @return \Pinenut\Model2\Updater
	 */
	function inc($field, $value) {
		// если есть сет - добавляем к нему
		if (isset($this->operators[static::OP_SET][$field])) {
			$this->operators[static::OP_SET][$field] += intval($value);
		}  elseif (isset($this->operators[static::OP_INC][$field])) {
			$this->operators[static::OP_INC][$field] += intval($value);
		} else {
			$this->operators[static::OP_INC][$field] = intval($value);
		}
		return $this;
	}
	
	/**
	 * @param string $field
	 */
	function getInc($field) {
		if (isset($this->operators[static::OP_INC][$field])) 
			return $this->operators[static::OP_INC][$field];
	}
	
	/**
	 * @param string $field
	 * @param mixed $value
	 * @return \Pinenut\Model2\Updater
	 */
	function set($field, $value) {
		// грохаем inc
		unset($this->operators[static::OP_INC][$field]);
		$this->operators[static::OP_SET][$field] = $value;
		return $this;
	}
	
	/**
	 * @param string $field
	 */
	function getSet($field) {
		if (isset($this->operators[static::OP_SET][$field])) 
			return $this->operators[static::OP_SET][$field];
	}

	function merge(Updater $updater) {
		
		if (isset($updater->operators[static::OP_REMOVEFROMSET]) && is_array($updater->operators[static::OP_REMOVEFROMSET]))
			foreach ($updater->operators[static::OP_REMOVEFROMSET] as $field=>$value) {
				foreach ($value as $val) {
					$this->removeFromSet($field, $val);
				}
			}
		if (isset($updater->operators[static::OP_ADDTOSET]) && is_array($updater->operators[static::OP_ADDTOSET])) 
			foreach ($updater->operators[static::OP_ADDTOSET] as $field=>$value) {
				$this->addToSet($field, $value);
			}
		if (isset($updater->operators[static::OP_INC]) && is_array($updater->operators[static::OP_INC]))
			foreach ((array)$updater->operators[static::OP_INC] as $field=>$value) {
				$this->inc($field, $value);
			}
		if (isset($updater->operators[static::OP_SET]) && is_array($updater->operators[static::OP_SET]))
			foreach ((array)$updater->operators[static::OP_SET] as $field=>$value) {
				$this->set($field, $value);
			}
	}
	
	function execute() {	
		$class = $this->class;
		return $class::execute($this);
	}
	
	/**
	 * Устанавливаем признак того, что будем удалять
	 */
	function delete() {
		$this->delete = true;
		return $this;
	}
	
	/** 
	 * Устанавливаем корректные имена в операциях 
	 * и просим родителя установить для условия
	 * @see library/Pinenut/Model2/Pinenut\Model2.Finder::applyFieldNames()
	 */
	function applyFieldNames() {
		
		$operators = array();
		foreach ($this->operators as $op => $data) {
			foreach ($data as $field => $value) {
				$newField = (!empty($this->_fieldNamePrefix)
					?$this->_fieldNamePrefix . ($field?'.':'')
					:'') . $field;
//				echo "applyFieldNames: $field -> $newField : $value <br>";
				$operators[$op][$newField] = $value;
			}
		}
		
		$this->operators = $operators;
		parent::applyFieldNames();
		
	}
	
	function getOperators() {
		return $this->operators;
	}
	
	function isInsert() {
		return $this->insert;
	}
	
	function isDelete() {
		return $this->delete;
	}
}